package netTrackerGUI;

import netTracker.network.*;
import netTracker.Util;
import netTracker.NetTracker;

/**
 * A thread to handle cell selection that is spawned
 * when a user tries to select a cell. The thread
 * will check to see if any other user has the cell
 * selected, and will not select the cell if they do.
 * 
 * @author David Cummings
 */
public class CellSelector {
	/** Utility class with debug flag: */
	Util util = new Util(this, true);
	
	TrackerPanel trackerPanel;
	CellGUI cell;
	/** The direction of movement */
	int moveX;
	int moveY;
	/** Indicates whether the selector is trying to move in a certain direction. */
	boolean moving;
	
	/**
	 * Constructs a cell selector to move to a cell given a direction to move.
	 * @param trackerPanel The tracker panel creating the thread.
	 * @param selectedCell The cell to move from.
	 * @param moveX the x amount to move. (positive is right)
	 * @param moveY the y amount to move. (positive is down)
	 */
	public CellSelector(TrackerPanel trackerPanel, CellGUI selectedCell, int moveX, int moveY){
		this.trackerPanel = trackerPanel;
		this.moveX = moveX;
		this.moveY = moveY;
		this.cell = trackerPanel.getCell(selectedCell.getCellX()+moveX,selectedCell.getCellY()+moveY);
		moving = true;
	}
	/**
	 * Constructs a cell selector to try to move to a given cell without a direction.
	 * @param trackerPanel The tracker panel creating the thread.
	 * @param targetCell The cell to move to.
	 */
	public CellSelector(TrackerPanel trackerPanel, CellGUI targetCell){
		this.trackerPanel = trackerPanel;
		this.cell = targetCell;
		moveX = 0;
		moveY = 0;
		moving = false;
	}
	
	public void attemptSelectCell() {
		if (trackerPanel.netTracker.isServer()){
			/** If we're the server, go ahead and check the lock and select the cell: */
			long startTime = System.nanoTime();
			checkAndSet();
			System.out.println("Server time to select: "+(System.nanoTime()-startTime));
			trackerPanel.netTracker.broadcastCellSelection(); // Notify connected users.
		} else {
			/** Otherwise, send a request to the session server.  */
			try{
				NetTracker.clientStartTime = System.nanoTime();
				if(moving){ // Send a MOVE request
					Message m = new Message("MOVE", moveX + "," + moveY, 
							trackerPanel.netTracker.getLocalAddress());
					trackerPanel.netTracker.sendMsg(m);	// send the message.
				}else{
					Message m = new Message("SELECTCELL", cell.getCellX() + "," + cell.getCellY(), 
							trackerPanel.netTracker.getLocalAddress());
					trackerPanel.netTracker.sendMsg(m);	// send the message.
				}
			}catch(PostalException e){
				util.debug(e);
			}
		}
	}
	
	private synchronized void checkAndSet(){
		if(trackerPanel.isLocking()){
			/** Check  to see if cell is selected over the network.
			 *  This operation should be in a critical section. */
			if(cell.getCell().isOutlined()){
				if (moving){	// If moving, keep trying to move until reaching an unoutlined cell.
					do{
						cell = trackerPanel.getCell(cell.getCellX()+moveX,cell.getCellY()+moveY);
					}while(cell.getCell().isOutlined());
					selectCell();	// At this point, we have reached an unoutlined cell.
				}
			}else{
				selectCell();	// If the cell is not already outlined, select it.
			} // end if (cell is outlined)
		}else{
			selectCell();	// When not locking, select the cell without question.
		} // end if (locking)
	}
	
	private void selectCell(){
		CellGUI current = trackerPanel.getSelectedCell();
		if(current!=null)
			current.deselect();
		cell.select();
		trackerPanel.setSelectedCell(cell);
	}
}
